package com.bj58.ecdata.dao.basedao;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.bj58.ecdata.dao.statementcreater.IStatementCreater;
import com.bj58.ecdata.dao.util.Common;
import com.bj58.ecdata.dao.util.PropertiesHelper;
import com.google.common.collect.Lists;

public abstract class DAOBase
  implements IDAO
{
  protected IStatementCreater psCreater;
  protected ConnectionHelper connHelper;
  protected int qurryTimeOut = 2;
  protected int insertUpdateTimeOut = 5;
  private static final String DB_CONFIG_PATH = "db.properties";
  protected static final Logger logger = LoggerFactory.getLogger(DAOBase.class);
  
  public static DAOHelper createIntrance()
    throws Exception
  {
    return createDAO(DB_CONFIG_PATH);
  }
  
  public static DAOHelper createIntrance(String configPath)
    throws Exception
  {
    return createDAO(configPath);
  }
  
  private static DAOHelper createDAO(String configPath)
    throws Exception
  {
    ConnectionHelper ch = new ConnectionHelper(configPath);
    PropertiesHelper ph = new PropertiesHelper(configPath);
    
    DAOHelper dao = new DAOHelper(ch);
    
    DAOBase sqlDAO = null;
    String sqlCreaterClass = ph.getString("SqlCreaterClass");
    if ((sqlCreaterClass != null) && (!sqlCreaterClass.equalsIgnoreCase("")))
    {
      if (sqlCreaterClass.equalsIgnoreCase("com.bj58.ecdata.dao.sqlcreate.SqlServerSQLCreater")) {
        sqlCreaterClass = "com.bj58.ecdata.dao.statementcreater.SqlServerPSCreater";
      }
      if (sqlCreaterClass.equalsIgnoreCase("com.bj58.ecdata.dao.sqlcreate.MySqlSQLCreater")) {
        sqlCreaterClass = "com.bj58.ecdata.dao.statementcreater.MysqlPSCreater";
      }
      logger.info("init SqlCreaterClass:" + sqlCreaterClass);
      IStatementCreater creater = (IStatementCreater)Class.forName(sqlCreaterClass).newInstance();
      sqlDAO = new DAOHandler(creater);
      sqlDAO.connHelper = ch;
      sqlDAO.qurryTimeOut = ph.getInt("QurryTimeOut");
      sqlDAO.insertUpdateTimeOut = ph.getInt("InsertUpdateTimeOut");
    }
    DAOBase procDAO = null;
    String procCreaterClass = ph.getString("ProcCreaterClass");
    if ((procCreaterClass != null) && (!procCreaterClass.equalsIgnoreCase("")))
    {
      if (procCreaterClass.equalsIgnoreCase("com.bj58.ecdata.dao.sqlcreate.BJ58AutoCreateProcParaCreater")) {
        procCreaterClass = "com.bj58.ecdata.dao.statementcreater.BJ58ProcCSCreater";
      }
      logger.info("init ProcCreaterClass:" + procCreaterClass);
      IStatementCreater creater = (IStatementCreater)Class.forName(procCreaterClass).newInstance();
      procDAO = new DAOHandler(creater);
      procDAO.connHelper = ch;
      procDAO.qurryTimeOut = ph.getInt("QurryTimeOut");
      procDAO.insertUpdateTimeOut = ph.getInt("InsertUpdateTimeOut");
    }
    dao.sql = sqlDAO;
    dao.proc = procDAO;
    
    logger.info("create DAOHelper success!");
    return dao;
  }
  
  protected <T> List<T> populateData(ResultSet resultSet, Class<T> clazz)
    throws Exception
  {
    List<T> dataList = Lists.newArrayList();
    List<Field> fieldList = Common.getAllFields(clazz);
    
    ResultSetMetaData rsmd = resultSet.getMetaData();
    int columnsCount = rsmd.getColumnCount();
    List<String> columnNameList = Lists.newArrayList();
    for (int i = 0; i < columnsCount; i++) {
      columnNameList.add(rsmd.getColumnLabel(i + 1).toLowerCase());
    }
    while (resultSet.next())
    {
      T bean = clazz.newInstance();
      for (Field f : fieldList)
      {
        String columnName = Common.getDBCloumnName(clazz, f).toLowerCase();
        if (columnNameList.contains(columnName))
        {
          Object columnValueObj = null;
          Class<?> filedCls = f.getType();
          if ((filedCls == Integer.TYPE) || (filedCls == Integer.class)) {
            columnValueObj = Integer.valueOf(resultSet.getInt(columnName));
          } else if (filedCls == String.class) {
            columnValueObj = resultSet.getString(columnName);
          } else if ((filedCls == Boolean.TYPE) || (filedCls == Boolean.class)) {
            columnValueObj = Boolean.valueOf(resultSet.getBoolean(columnName));
          } else if ((filedCls == Byte.TYPE) || (filedCls == Byte.class)) {
            columnValueObj = Byte.valueOf(resultSet.getByte(columnName));
          } else if ((filedCls == Short.TYPE) || (filedCls == Short.class)) {
            columnValueObj = Short.valueOf(resultSet.getShort(columnName));
          } else if ((filedCls == Long.TYPE) || (filedCls == Long.class)) {
            columnValueObj = Long.valueOf(resultSet.getLong(columnName));
          } else if ((filedCls == Float.TYPE) || (filedCls == Float.class)) {
            columnValueObj = Float.valueOf(resultSet.getFloat(columnName));
          } else if ((filedCls == Double.TYPE) || (filedCls == Double.class)) {
            columnValueObj = Double.valueOf(resultSet.getDouble(columnName));
          } else if (filedCls == BigDecimal.class) {
            columnValueObj = resultSet.getBigDecimal(columnName);
          } else {
            columnValueObj = resultSet.getObject(columnName);
          }
          if (columnValueObj != null)
          {
            Method setterMethod = Common.getSetterMethod(clazz, f);
            setterMethod.invoke(bean, new Object[] { columnValueObj });
          }
        }
      }
      dataList.add(bean);
    }
    return dataList;
  }
}
